home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / ccdl151s.zip / SOURCE / REG68.C < prev    next >
C/C++ Source or Header  |  1997-06-07  |  6KB  |  236 lines

  1. /*
  2.  * 68K/386 32-bit C compiler.
  3.  *
  4.  * copyright (c) 1997, David Lindauer
  5.  * 
  6.  * This compiler is intended for educational use.  It may not be used
  7.  * for profit without the express written consent of the author.
  8.  *
  9.  * It may be freely redistributed, as long as this notice remains intact
  10.  * and either the original sources or derived sources 
  11.  * are distributed along with any executables derived from the originals.
  12.  *
  13.  * The author is not responsible for any damages that may arise from use
  14.  * of this software, either idirect or consequential.
  15.  *
  16.  * v1.35 March 1997
  17.  * David Lindauer, gclind01@starbase.spd.louisville.edu
  18.  *
  19.  * Credits to Mathew Brandt for original K&R C compiler
  20.  *
  21.  */
  22. #include        <stdio.h>
  23. #include        "expr.h"
  24. #include        "c.h"
  25. #include        "gen68.h"
  26.  
  27. /*
  28.  *      this module handles the allocation and de-allocation of
  29.  *      temporary registers. when a temporary register is allocated
  30.  *      the stack depth is saved in the field deep of the address
  31.  *      mode structure. when validate is called on an address mode
  32.  *      structure the stack is popped until the register is restored
  33.  *      to it's pre-push value.
  34.  */
  35. extern int cf_freedata,cf_freeaddress,cf_freefloat,maxdata,maxaddress;
  36.  
  37. AMODE    push[] = { {am_adec,7} },
  38.                 pop[] = { {am_ainc,7} };
  39. int             next_data,        /* Next available */
  40.                 next_addr;
  41. int             max_data,            /* Max available */
  42.                 max_addr;
  43. int                            next_float, max_float;
  44. long stackdepth,framedepth;
  45.  
  46. char regstack[20],rsold[30],rsdepth = 0,rsodepth=0;
  47. char aregs[8],dregs[8],fregs[8];
  48.  
  49. void regini(void)
  50. {
  51.     int i;
  52.     for (i=0; i < 8; i++) {
  53.         aregs[0] = dregs[0] = fregs[0] = 0;
  54.     }
  55.     rsdepth = rsodepth = 0;
  56. }
  57. void gen_push(int reg, int rmode, int flag)
  58. /*
  59.  *      this routine generates code to push a register onto the stack
  60.  */
  61. {       AMODE    *ap1;
  62.         ap1 = xalloc(sizeof(AMODE));
  63.         ap1->preg = reg;
  64.         ap1->mode = rmode;
  65.                 if (rmode == am_freg) {
  66.           gen_code(op_fmove,10,ap1,push);
  67.                     stackdepth +=8;
  68.                 }
  69.                 else {
  70.           gen_code(op_move,4,ap1,push);
  71.                     stackdepth +=4;
  72.                 }
  73. }
  74.  
  75. void gen_pop(int reg, int rmode, int flag)
  76. /*
  77.  *      generate code to pop the primary register in ap from the
  78.  *      stack.
  79.  */
  80. {       AMODE    *ap1;
  81.         ap1 = xalloc(sizeof(AMODE));
  82.         ap1->preg = reg;
  83.         ap1->mode = rmode;
  84.                 if (rmode == am_freg) {
  85.             gen_code(op_fmove,10,pop,ap1);
  86.                     stackdepth -=8;
  87.                 }
  88.                 else {
  89.             gen_code(op_move,4,pop,ap1);
  90.                     stackdepth -=4;
  91.                 }
  92. }
  93. void initstack(void)
  94. /*
  95.  *      this routine should be called before each expression is
  96.  *      evaluated to make sure the stack is balanced and all of
  97.  *      the registers are marked free.
  98.  */
  99. {
  100.     int i;
  101.     for (i=0; i < 8; i++) 
  102.         aregs[0] = dregs[0] = fregs[0] = 0;
  103.             rsdepth = rsodepth = 0;
  104.        next_data = 0;
  105.         next_addr = 0;
  106.         max_data = cf_freedata-1;
  107.         max_addr = cf_freeaddress-1;
  108.             next_float = 0;
  109.             max_float = cf_freefloat-1;
  110. }
  111.  
  112. void mark(void)
  113. {
  114.     rsold[rsodepth++] = rsdepth;
  115. }
  116. void release(void)
  117. {
  118.     if (!rsodepth)
  119.         return;
  120.     rsodepth--;
  121.     while (rsdepth > rsold[rsodepth]) {
  122.         int data = regstack[--rsdepth];
  123.         if (data <8) {
  124.             gen_pop(data,am_dreg,0);
  125.             dregs[data] = 1;
  126.         }
  127.         else
  128.             if (data < 16) {
  129.                 gen_pop(data & 7,am_areg,0);
  130.                 aregs[data-8] = 1;
  131.             }
  132.             else {
  133.                 gen_pop(data & 7,am_freg,0);
  134.                 fregs[data-16] = 1;
  135.             }
  136.     }
  137.      max_addr = next_addr < cf_freeaddress ? cf_freeaddress-1 : next_addr-1;
  138.     max_data = next_data < cf_freedata ? cf_freedata-1 : next_data-1;
  139.     max_float = next_float < cf_freefloat ? cf_freefloat-1 : next_float-1;
  140. }
  141. AMODE    *temp_data(void)
  142. /*
  143.  *      allocate a temporary data register and return it's
  144.  *      addressing mode.
  145.  */
  146. {       AMODE    *ap;
  147.         ap = xalloc(sizeof(AMODE));
  148.         ap->mode = am_dreg;
  149.         ap->preg = next_data % cf_freedata;
  150.         if( next_data > max_data )
  151.                 {
  152.                 gen_push(ap->preg,am_dreg,0);
  153.                                 dregs[ap->preg] = 1;
  154.                                 regstack[rsdepth++] = ap->preg;
  155.                 max_data = next_data;
  156.                 }
  157.         ++next_data;
  158.         return ap;
  159. }
  160.  
  161. AMODE    *temp_addr(void)
  162. /*
  163.  *      allocate a temporary address register and return it's
  164.  *      addressing mode.
  165.  */
  166. {       AMODE    *ap;
  167.         ap = xalloc(sizeof(AMODE));
  168.         ap->mode = am_areg;
  169.         ap->preg = next_addr % cf_freeaddress;
  170.         if( next_addr > max_addr )
  171.                 {
  172.                 gen_push(ap->preg,am_areg,0);
  173.                                 aregs[ap->preg] = 1;
  174.                                 regstack[rsdepth++] = ap->preg+8;
  175.                 max_addr = next_addr;
  176.                 }
  177.         ++next_addr;
  178.         return ap;
  179. }
  180. AMODE    *temp_float(void)
  181. /*
  182.  *      allocate a temporary address register and return it's
  183.  *      addressing mode.
  184.  */
  185. {       AMODE    *ap;
  186.         ap = xalloc(sizeof(AMODE));
  187.         ap->mode = am_freg;
  188.         ap->preg = next_float % cf_freefloat;
  189.         if( next_float > max_float )
  190.                 {
  191.                 gen_push(ap->preg,am_freg,0);
  192.                                 fregs[ap->preg] = 1;
  193.                                 regstack[rsdepth++] = ap->preg+16;
  194.                 max_addr = next_float;
  195.                 }
  196.         ++next_float;
  197.         return ap;
  198. }
  199. void freedata(int dreg)
  200. {
  201.     if (dreg < cf_freedata && next_data > 0) {
  202.         dregs[dreg] = 0;
  203.         --next_data;
  204.     }
  205. }
  206. void freeaddr(int areg)
  207. {
  208.     if (areg < cf_freeaddress && next_addr > 0) {
  209.         aregs[areg] = 0;
  210.         --next_addr;
  211.     }
  212. }
  213.         
  214. void freeop(AMODE *ap)
  215. /*
  216.  *      release any temporary registers used in an addressing mode.
  217.  */
  218. {       if( ap->mode == am_immed || ap->mode == am_direct )
  219.                 return;         /* no registers used */
  220.         if( ap->mode == am_dreg)
  221.                     freedata(ap->preg);
  222.         else if( ap->mode == am_areg || ap->mode == am_ind || ap->mode == am_indx || ap->mode == am_adec || ap->mode == am_ainc)
  223.                     freeaddr(ap->preg);
  224.         else if( ap->mode == am_freg && ap->preg < cf_freefloat && next_float>0) {
  225.                                     fregs[ap->preg] = 0;
  226.                     --next_float;
  227.                 }
  228.                 else if (ap->mode == am_baseindxdata) {
  229.                     freeaddr(ap->preg);
  230.                     freedata(ap->sreg);
  231.                 }
  232.                 else if (ap->mode == am_baseindxaddr) {
  233.                     freeaddr(ap->preg);
  234.                     freeaddr(ap->sreg);
  235.                 }
  236. }